/* 
 *  MacroCamera.java
 *  Simple "macro recorder".
 *  Author: Petr Sturc <psturc@gemalto.com>
 */

package com.gemalto.Kryptik.MacroCamera;

import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.*;
import javax.swing.text.*;
import com.gemalto.Kryptik.*;
import java.util.LinkedList;
import bsh.*;

public class MacroCamera implements DocumentListener, KeyListener, ActionListener {

	private StringBuffer macro;
	private boolean recording;	
	private static MacroCamera instance;
	private boolean paste, keyPressed, clickBlock=false, selection;
	

	// Singleton pattern is applied here -> constructor is private
	private MacroCamera(){
		macro=new StringBuffer(256);
		recording=false;
		// MacroCamera should be exported to BeanShell
		Beanshell.setVariable("macroCamera",this);
	}


	// This is how to get an instance of MacroCamera
	public static MacroCamera getInstance(){
		if (instance==null){
			instance=new MacroCamera();
		}
		return instance;
	}
		

	// 4 main methods of MacroCamera = record, stop, play and show
	public void record(){
		recording=true;
		macro=new StringBuffer();
	}

	public void stop(){
		recording=false;
	}
	
	public void play(){
		Interpreter i = Beanshell.newInterpreter();
		try {
				i.eval(macro.toString());
		} catch (EvalError e){
				Messenger.error("Error in macro: "+e.toString());
		}
	}


	public void show(){
		System.out.println(macro);
	}






	// **************** DOCUMENT LISTENER ******************* //

	// When is changedUpdate invoked ????
	public void changedUpdate(DocumentEvent e){
	}

	public void insertUpdate(DocumentEvent e){
		if ( keyPressed){
			if (recording){
					int offset=e.getOffset();
					int length=e.getLength();
					Document d=e.getDocument();
					String name=(String)d.getProperty("name");

				if (paste){
						macro.append(name+".setCaretPosition("+offset+");\n");
						macro.append(name+".paste();\n");
						paste=false;
				} else {
						try{
							String text=d.getText(offset,length);
							macro.append(name+".insert(\""+text+"\","+offset+");\n");
						} catch (BadLocationException ble){
						}
				}
			}
			keyPressed=false;
		} 
	}

	public void removeUpdate(DocumentEvent e){
		if (recording){
				if (!clickBlock){
//				try{
					int offset=e.getOffset();
					int length=e.getLength();
					Document d=e.getDocument();
					String name=(String)d.getProperty("name");
					macro.append(name+".replaceRange(\"\","+offset+","+(offset+length)+");\n");
//				} catch (BadLocationException ble){

				} else {
					clickBlock=false;
				}
		}
	}

	
	// ***************** KEY LISTENER ************************ //
	public void keyPressed(KeyEvent e){
		if (recording){
			keyPressed=true;
			JTextComponent source = (JTextComponent)e.getSource();
			Document d = source.getDocument();
			String name = (String)d.getProperty("name");
			int offset = source.getCaretPosition();
			if (e.isControlDown()){
					switch ((int)e.getKeyCode()){
						case KeyEvent.VK_C:
						case KeyEvent.VK_X:
							if (source.getSelectedText()!=null){
								if (!selection){
									int selectionStart = source.getSelectionStart();
									int selectionEnd = source.getSelectionEnd();
									macro.append(name+".select("+selectionStart+","+selectionEnd+");\n");
								} else {
									selection=false;
								}
								macro.append(name+".copy();\n");
							}
							break;
						case KeyEvent.VK_V:
							if (e.isShiftDown()){
									e.setModifiers(InputEvent.CTRL_MASK);
									paste=false;
							} else paste=true;
							break;
						case KeyEvent.VK_A:
							macro.append(name+".selectAll();\n");
							selection=true;
							break;
					}
			} else if (e.isShiftDown()){
				switch ((int)e.getKeyCode()) {
					case KeyEvent.VK_END:
						System.out.println("----- END ------");
						int selectionStart = source.getSelectionStart();
						int selectionEnd = source.getSelectionEnd();
						if (source.getSelectedText()!=null){
						System.out.println("----- SELECTED ------");
							macro.append(name+".select("+selectionStart+","+name+".getText().length());\n");
							selection=true;
						}
				}
			}
 		}

	}

	public void keyReleased(KeyEvent e){
	}

	public void keyTyped(KeyEvent e){
	}

	// ***************** ACTION LISTENER ************************ //
	
	public void actionPerformed(ActionEvent e){
		if (recording){
			JButton source = (JButton)e.getSource();
			String command = e.getActionCommand();

			if (command.equals("ENCRYPT")){
				macro.append("encryptButton.doClick();\n");
			} else if (command.equals("DECRYPT")){
				macro.append("decryptButton.doClick();\n");
			} else if (command.equals("SIGN")){
				macro.append("signButton.doClick();\n");
			} 
			clickBlock=true;
		}
	}
}

// vim:ts=4
